import axios from 'axios';
import type { AxiosRequestConfig, InternalAxiosRequestConfig, Canceler } from 'axios';
import { message } from 'ant-design-vue';
import { useUserStore, useCommonStore } from '@/store'
import { getUserToken, saveUserToken } from '@/utils/cache'; // 引入新的Token获取函数
import { refreshToken } from '@/api/user';

/** @name 自定义配置 **/
interface CustomOptions {
    /** @name 是否开启loading层效果，默认为false **/
    loading: boolean,
    /** @name 是否开启取消重复请求，默认为 true **/
    repeat_request_cancel: boolean,
    /** @name 是否开启简洁的数据结构响应，默认为true **/
    reduct_data_format: boolean,
    /** @name 是否开启接口错误信息展示，默认为true **/
    error_message_show: boolean,
    /** @name 是否开启code不为0时的信息提示，默认为false **/
    code_message_show: boolean,
    /** @name 自定义错误处理函数 **/
    errorHandler?: (error: any) => void,
}

// 定义响应数据接口，提高类型安全性
interface ApiResponse<T = any> {
    code: number;
    data: T;
    message?: string;
    msg?: string; // 有些接口返回msg而不是message
    time?: number;
}

const pendingMap: Map<string, Canceler> = new Map();

// 定义多个 API 请求的基础 URL 前缀，并确保有一个DEFAULT键
const API_PREFIXES = {
    API1: import.meta.env.VITE_API_BASEURL,
    API2: import.meta.env.VITE_BACKUP_API_BASEURL,
    API3: import.meta.env.VITE_KEFU_API_BASEURL,
    DEFAULT: import.meta.env.VITE_API_BASEURL
};


/**
 * 根据运行环境获取基础请求URL
 */
export const getUrl = (): string => {
    const value: string = import.meta.env.VITE_KEFU_API_BASEURL as string
    return value == 'getCurrentDomain' ? window.location.protocol + '//' + window.location.host : value
}

/**
 * 根据运行环境获取基础请求URL的端口
 */
export const getUrlPort = (): string => {
    const url = getUrl()
    return new URL(url).port
}

/**
 * @name 基于axios的二次封装
 * @param { AxiosRequestConfig } axiosConfig axios配置
 * @param { string? } prefix API前缀标识符，用于选择不同的API基础URL
 * @param { Partial<CustomOptions>? } customOptions 自定义配置
 * @param { any? } customHeaders 自定义请求头
 * @returns { Promise<any> } 请求结果
 */
function myAxios<T = any>(
    axiosConfig: AxiosRequestConfig,
    prefix: string = 'DEFAULT',
    customOptions?: Partial<CustomOptions>,
): Promise<ApiResponse<T>> {
    const userStore = useUserStore();
    const commonStore = useCommonStore();
    const currency = 'USD'; // 考虑将货币设置为可配置项

    // 获取基础URL，确保有一个合理的默认值
    const baseURL = API_PREFIXES[prefix] || API_PREFIXES.DEFAULT;

    // 调试日志 - 看看实际使用的baseURL
    // console.log(`Making request to ${axiosConfig.url} with baseURL: ${baseURL}`);

    const service = axios.create({
        baseURL, // 设置统一的请求前缀
        timeout: 100000, // 设置统一的超时时长
        headers: {
            'Content-Type': 'application/json', // 设置默认的请求头为 JSON 格式
            'Currency': currency,
            'think-lang': 'en',
            ...axiosConfig.headers
        },
    });

    // 自定义配置
    const custom_options: CustomOptions = {
        loading: false,
        repeat_request_cancel: true,
        reduct_data_format: true,
        error_message_show: true,
        code_message_show: false,
        ...customOptions
    };

    // 请求拦截
    service.interceptors.request.use(
        config => {
            // 取消重复请求
            removePending(config);
            if (custom_options.repeat_request_cancel) {
                addPending(config);
            }

            // 处理 loading 状态
            if (custom_options.loading) {
                commonStore.setCurRequestNum(true);
            }

            // 从缓存系统获取 token
            const token = getUserToken();

            // 添加 token 到请求头
            if (token && typeof window !== "undefined") {
                config.headers['ba-user-token'] = token;
                // 同时保持兼容性，也设置 Authorization 头
                config.headers.Authorization = token;
            }

            return config;
        },
        error => {
            return Promise.reject(error);
        }
    );

    // 响应拦截
    service.interceptors.response.use(
        response => {
            removePending(response.config);

            // 关闭 loading
            if (custom_options.loading) {
                closeLoading();
            }

            // 处理业务错误码 - 将 code 1 视为成功
            if (response.data &&
                (response.data.code !== 0 && response.data.code !== 1 && response.data.code !== 200 && response.data.code !== undefined)) {
                // 根据配置决定是否显示错误消息
                if (custom_options.code_message_show) {
                    message.error(response.data.message || response.data.msg || '请求失败');
                }
                // return Promise.reject(response.data);
            }

            // 根据配置返回完整响应或仅返回数据部分
            return custom_options.reduct_data_format ? response.data : response;
        },
        error => {
            // 清理相关状态
            error.config && removePending(error.config);

            if (custom_options.loading) {
                closeLoading();
            }

            // 如果是409状态码，直接返回响应，则刷新token
            if (error.response && error.response.status === 409) {
                refreshToken().then((res: any) => {
                    if (res.code === 200) {
                        saveUserToken(res.result.token);
                    }
                })
                return Promise.resolve(error.response);
            }

            // 处理 401 认证错误
            if (error.response && error.response.status === 401) {
                localStorage.clear()
                // 可以在这里添加自动刷新 token 或跳转到登录页的逻辑
                message.error('You are not logged in at present. Please log in first!');
                // 跳转登录页
                // setTimeout(() => {
                //     window.location.href = '/login';
                // }, 1500);
                return Promise.resolve(error.response);
            }

            // 使用自定义错误处理或默认错误处理
            if (custom_options.errorHandler) {
                custom_options.errorHandler(error);
            } else if (custom_options.error_message_show) {
                httpErrorStatusHandle(error);
            }

            return Promise.reject(error);
        }
    );

    return service(axiosConfig);
}

/** @name 关闭loading **/
function closeLoading() {
    setTimeout(() => {
        const commonStore = useCommonStore();
        commonStore.setCurRequestNum(false); // 记录请求池中请求的数量
    }, 100);
}

/** @name 记录接口 **/
function addPending(config: InternalAxiosRequestConfig<any>) {
    const pendingKey = getPendingKey(config);

    config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
        if (!pendingMap.has(pendingKey)) {
            pendingMap.set(pendingKey, cancel);
        } else {
            // 如果已存在相同请求，取消当前请求
            cancel(`重复请求已取消: ${pendingKey}`);
        }
    });
}

/** @name 移除接口 **/
function removePending(config: InternalAxiosRequestConfig<any>) {
    const pendingKey = getPendingKey(config);
    if (pendingMap.has(pendingKey)) {
        const cancel = pendingMap.get(pendingKey);
        cancel && cancel(`重复请求已取消: ${pendingKey}`);
        pendingMap.delete(pendingKey);
    }
}

/** @name 通过接口请求信息生成唯一的key **/
function getPendingKey(config: InternalAxiosRequestConfig<any>) {
    let { url, method, params, data } = config;

    // 修改：首先将所有参数转换为字符串，确保格式一致
    if (typeof data === 'string') {
        try {
            data = JSON.parse(data);
        } catch (e) {
            // 如果解析失败，使用原始字符串
        }
    }

    // 安全处理 params 和 data，避免 JSON.stringify 出错
    const safeStringify = (obj: any) => {
        if (obj === undefined || obj === null) {
            return '';
        }
        try {
            return JSON.stringify(obj);
        } catch (e) {
            return '';
        }
    };

    // 改进：将url路径和参数清晰分开，排除可能不影响相同性判断的因素
    url = url || '';
    method = method || 'GET';

    // 生成唯一键时确保对象属性顺序一致(先排序对象属性)
    const normalizeObject = (obj: any) => {
        if (!obj || typeof obj !== 'object') return obj;

        // 对于对象，排序所有键然后转换
        if (!Array.isArray(obj)) {
            const sortedObj: any = {};
            Object.keys(obj).sort().forEach(key => {
                sortedObj[key] = obj[key];
            });
            return sortedObj;
        }

        // 数组不需要特殊处理
        return obj;
    };

    // 处理传入的参数和数据，确保它们有一致的格式用于比较
    const normalizedParams = normalizeObject(params);
    const normalizedData = normalizeObject(data);

    // 生成请求的唯一键，用于识别重复请求
    return [url, method, safeStringify(normalizedParams), safeStringify(normalizedData)].join('&');
}

/** @name 接口异常时，预订制message **/
function httpErrorStatusHandle(error: any) {
    if (axios.isCancel(error)) {
        // 取消请求的错误不需要展示给用户
        return;
    }

    let messageString = '';

    if (error && error.response) {
        // 根据不同的HTTP状态码定制错误信息
        switch (error.response.status) {
            // case 400: messageString = '请求参数错误'; break;
            case 401: messageString = '未授权，请重新登录'; break;
            case 403: messageString = '拒绝访问'; break;
            case 404: messageString = '请求的资源不存在'; break;
            case 500: messageString = '服务器内部错误'; break;
            default: messageString = error.response.data?.msg || '未知错误';
        }
    } else {
        if (error.message.includes('timeout')) {
            messageString = '网络请求超时！';
        } else if (error.message.includes('Network')) {
            messageString = window.navigator.onLine ? '服务端异常！' : '您断网了！';
        } else {
            messageString = '未知错误';
        }
    }

    message.error(messageString);
}

export default myAxios;
